from typing import Optional
from django.contrib.auth import get_user_model
from rest_framework import serializers
from django.shortcuts import reverse

from .. import models

from project import models as p_models

default_queryset = (
    models.AuditManagement.objects
    .select_related('content_type', 'auditor')
    .all()
)

User = get_user_model()

class AuditManagementListSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        # Create a map of instance ID to instance
        instance_map = {i.id: i for i in instance}
        
        # Perform updates and return results
        ret = []
        for inst, data in zip(instance, validated_data):
            ret.append(self.child.update(inst, data))
            
        return ret

        
class AuditManagementSerializer(serializers.ModelSerializer):
    """used for write."""
    """
    You need to implement `get_link` if you want to get a working url.
    """
    link = serializers.SerializerMethodField()
    
    class Meta:
        model = models.AuditManagement
        fields = ['id', 'content_type', 'object_id', 'status', 'comment', 'auditor',
                  'updated_at', 'link']
        list_serializer_class = AuditManagementListSerializer
        
    def get_link(self, am: models.AuditManagement) -> Optional[str]:
        return None

class AuditManagementReadSerializer(AuditManagementSerializer):
    auditor = serializers.SlugRelatedField(
        read_only=True,
        slug_field='username'
    )

    
class UserAuditSerializer(AuditManagementReadSerializer):
    username = serializers.SerializerMethodField()
    full_name = serializers.SerializerMethodField()
    link = serializers.SerializerMethodField()
    
    class Meta:
        model = models.AuditManagement
        fields = AuditManagementReadSerializer.Meta.fields + ['full_name', 'username']

    def get_full_name(self, am: models.AuditManagement):
        return am.content_object.get_full_name()

    def get_username(self, am: models.AuditManagement):
        return am.content_object.username
    
    def get_link(self, am: models.AuditManagement):
        return reverse("admin:user_userprofile_change", args=[am.content_object.pk])

    
class ProjectInfoSerializer(AuditManagementReadSerializer):
    project_name = serializers.SerializerMethodField()
    project_id = serializers.SerializerMethodField()
    
    class Meta:
        model = models.AuditManagement
        fields = AuditManagementReadSerializer.Meta.fields + ['project_name', 'project_id']
        
    def get_project_name(self, am: models.AuditManagement):
        return am.content_object.chinese_name

    def get_project_id(self, am: models.AuditManagement):
        return am.object_id

    def get_link(self, am: models.AuditManagement):
        return reverse("project:detail", kwargs={'pk': am.object_id})

    
class ProjectSubSerializer(AuditManagementReadSerializer):
    project_name = serializers.SerializerMethodField()
    project_id = serializers.SerializerMethodField()
    
    class Meta:
        model = models.AuditManagement
        fields = AuditManagementReadSerializer.Meta.fields + ['project_name', 'project_id']

    def get_project_name(self, am: models.AuditManagement):
        return am.content_object.project.chinese_name
        
    def get_project_id(self, am: models.AuditManagement):
        return am.content_object.project.id

    def get_link(self, am: models.AuditManagement):
        obj = am.content_object
        return obj.get_link(obj.project.id, obj.id)
        
    
class FileAuditSerializer(AuditManagementReadSerializer):
    filename = serializers.SerializerMethodField()
    file_size = serializers.SerializerMethodField()
    uploaded_at = serializers.SerializerMethodField()
    owner = serializers.SerializerMethodField()
    requester = serializers.SerializerMethodField()
    link = serializers.SerializerMethodField()
    
    class Meta:
        model = models.AuditManagement
        fields = (
            AuditManagementReadSerializer.Meta.fields +
            ['filename', 'file_size', 'uploaded_at', 'owner', 'requester']
        )

    def get_filename(self, am: models.AuditManagement):
        return am.content_object.filename
    
    def get_file_size(self, am: models.AuditManagement):
        return am.content_object.file_size
    
    def get_uploaded_at(self, am: models.AuditManagement):
        return am.content_object.uploaded_at
    
    def get_owner(self, am: models.AuditManagement):
        return am.content_object.owner.username

    def get_requester(self, am: models.AuditManagement):
        if not hasattr(am, 'requester_username'):
            raise Exception("Requester not found!")
        return am.requester_username

    def get_link(self, am: models.AuditManagement):
        return reverse("media:raw", kwargs={ 'pk': am.content_object.uuid })
    
            
        

